#include "task_autoMode.h"

#include "tasksInit.h"
#include "task_cntlCenter.h"
#include "task_sensorData.h"

#include <stdio.h>
#include <stdlib.h>

#include "los_task.h"
#include "los_event.h"
#include "los_tick.h"
#include "los_memory.h"
#include "los_mux.h"
#include "los_queue.h"

unsigned int task_autoMode_id;
TSK_INIT_PARAM_S task_autoMode_handler = {
    (TSK_ENTRY_FUNC)task_autoMode,
    23,             //TaskPrio
    0,              //Arg
    1280,            //stack size
    "task_autoMode",//Name
    0               //resved
};

// typedef void(*mode_loop_func_t)(void);

static void task_manual_mode(void);
static void task_away_mode(void);
static void task_home_mode(void);

unsigned int task_manual_mode_id, task_away_mode_id, task_home_mode_id;
TSK_INIT_PARAM_S task_manual_mode_handler = {
    (TSK_ENTRY_FUNC)task_manual_mode,
    28,             //TaskPrio
    0,              //Arg
    1280,            //stack size
    "task_manual_mode",//Name
    0               //resved
},
task_away_mode_handler = {
    (TSK_ENTRY_FUNC)task_away_mode,
    28,             //TaskPrio
    0,              //Arg
    1280,            //stack size
    "task_away_mode",//Name
    0               //resved
},
task_home_mode_handler = {
    (TSK_ENTRY_FUNC)task_home_mode,
    28,             //TaskPrio
    0,              //Arg
    1280,            //stack size
    "task_home_mode",//Name
    0               //resved
};

typedef enum
{
    SCENE_MANUAL_MODE,  //手动模式
    SCENE_AWAY_MODE,    //离家模式
    SCENE_HOME_MODE    //回家模式
}scene_mode_t;

#define TEMPERATURE_THRESHOLD_H     23
#define TEMPERATURE_THRESHOLD_L     21

#define HUMIDITY_THRESHOLD_H        70
#define HUMIDITY_THRESHOLD_L        60

#define LUMINANCE_THRESHOLD_H       45
#define LUMINANCE_THRESHOLD_L       10

// static int switch_task(uint32_t cur_task_id, )
// {
    
// }

void task_autoMode(void)
{
    LOS_EventRead(&bspInit_ECB, BSPINIT_EVENT_INITOK, LOS_WAITMODE_AND, LOS_WAIT_FOREVER);

    int ret =0;

    event_mode_switch_t event = EVENT_MODE_NO_SWITCH;
    uint32_t event_size = sizeof(event);

    uint32_t* pCurId = &task_manual_mode_id;
    TSK_INIT_PARAM_S* pCurHandle = &task_manual_mode_handler;

    ret = LOS_TaskCreate(pCurId, pCurHandle);
    if(ret != LOS_OK)
    {
        printf("[task autoMode] LOS_TaskCreate task_manual_mode error, ret: 0x%x.\n", ret);
    }

    while(1)
    {
        event = EVENT_MODE_NO_SWITCH;

        //读模式转换事件队列
        LOS_QueueReadCopy(autoMode_qId, &event, &event_size, LOS_WAIT_FOREVER);

        // printf("[task autoMode] switching event:%d.\n", event);

        switch(event)
        {
        case EVENT_MODE_SWITCH_TO_AWAY:
            //删除当前模式任务
            ret = LOS_TaskDelete(*pCurId);
            if(ret != LOS_OK)
            {
                printf("[task autoMode] LOS_TaskDelete previous_task error, ret: 0x%x.\n", ret);
            }

            //创建新模式任务
            pCurId = &task_away_mode_id;
            pCurHandle = &task_away_mode_handler;
            ret = LOS_TaskCreate(pCurId, pCurHandle);
            if(ret != LOS_OK)
            {
                printf("[task autoMode] LOS_TaskCreate task_away_mode error, ret: 0x%x.\n", ret);
            }

            printf("[task autoMode] switching to away mode.\n");
            break;
        case EVENT_MODE_SWITCH_TO_HOME:
            //删除当前模式任务
            ret = LOS_TaskDelete(*pCurId);
            if(ret != LOS_OK)
            {
                printf("[task autoMode] LOS_TaskDelete previous_task error, ret: 0x%x.\n", ret);
            }

            //创建新模式任务
            pCurId = &task_home_mode_id;
            pCurHandle = &task_home_mode_handler;
            ret = LOS_TaskCreate(pCurId, pCurHandle);
            if(ret != LOS_OK)
            {
                printf("[task autoMode] LOS_TaskCreate task_away_mode error, ret: 0x%x.\n", ret);
            }

            printf("[task autoMode] switching to home mode.\n");
            break;

        case EVENT_MODE_SWITCH_TO_MANUAL:
            //删除当前模式任务
            ret = LOS_TaskDelete(*pCurId);
            if(ret != LOS_OK)
            {
                printf("[task autoMode] LOS_TaskDelete previous_task error, ret: 0x%x.\n", ret);
            }

            //创建新模式任务
            pCurId = &task_manual_mode_id;
            pCurHandle = &task_manual_mode_handler;
            ret = LOS_TaskCreate(pCurId, pCurHandle);
            if(ret != LOS_OK)
            {
                printf("[task autoMode] LOS_TaskCreate task_away_mode error, ret: 0x%x.\n", ret);
            }

            printf("[task autoMode] switching to manual mode.\n");
            break;

        case EVENT_MODE_NO_SWITCH:
            break;

        default:
            break;
        }
        
        LOS_Msleep(200);
    }
}

void task_manual_mode(void)
{
    //do nothing
    while(1)
    {
        LOS_Msleep(1000);
    }
}

void task_away_mode(void)
{
    cntl_msg_t cntl_msg;
    int rand_light, rand_delay_ms;

    //关闭所有设备
    cntl_msg.source = CNTL_MSG_SOURCE_FROM_AUTOMODE;
    cntl_msg.type = CNTL_MSG_TYPE_CLOSE_ALL;
    LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);

    LOS_Msleep(10000);   //等待10秒
    
    //初始化随机函数
    srand(LOS_TickCountGet());

    while(1)
    {
        rand_light = rand() % 3;    // 0 1 2
        rand_delay_ms = 2000 + rand() % 7000;

        //设置指令参数
        cntl_msg.type = CNTL_MSG_TYPE_ID;
        cntl_msg.id = rand_light;
        cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
        *(int*)cntl_msg.param = 100;
        // LOS_QueueWriteCopy();
        //发送开灯指令
        LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        
        LOS_Msleep(rand_delay_ms);

        //关灯指令
        cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
        *(int*)cntl_msg.param = 0;

        LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);

        LOS_Msleep(1000);
    }
}

void task_home_mode(void)
{
    cntl_msg_t cntl_msg;
    cntl_msg.source = CNTL_MSG_SOURCE_FROM_AUTOMODE;
    cntl_msg.type = CNTL_MSG_TYPE_ID;

    while(1)
    {
        //获取环境数据
        sensor_data_t env_data;
        LOS_MuxPend(sensor_data_mux, LOS_WAIT_FOREVER);
        env_data = sensor_data;
        LOS_MuxPost(sensor_data_mux);

        //开客厅灯
        // if(env_data.lumi_lux > LUMINANCE_THRESHOLD_H)
        // {
        //     //开窗帘
        //     cntl_msg.id = 7;    //窗帘id
        //     cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
        //     *(int*)cntl_msg.param = 1;
        //     LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);

        //     LOS_Msleep(3000);

        //     cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
        //     *(int*)cntl_msg.param = 0;
        //     LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        // }
        // if(env_data.lumi_lux < LUMINANCE_THRESHOLD_L)
        // {
            //开客厅灯
            cntl_msg.id = 1;
            cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
            *(int*)cntl_msg.param = 100;
            LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        // }        

        //温度超过H阈值自动打开空调，低于L阈值自动关闭空调
        cntl_msg.id = 5;    //空调id
        cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
        if(env_data.tempe_c > TEMPERATURE_THRESHOLD_H)
        {
            *(int*)cntl_msg.param = 1;
            LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        }
        else if(env_data.tempe_c < TEMPERATURE_THRESHOLD_L)
        {
            *(int*)cntl_msg.param = 0;
            LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        }

        //湿度低于L阈值自动打开加湿器，高于H阈值自动关闭加湿器
        cntl_msg.id = 8;    //加湿器id
        cntl_msg.param = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(int));
        if(env_data.humidity < HUMIDITY_THRESHOLD_L)
        {
            *(int*)cntl_msg.param = 1;
            LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        }
        else if(env_data.humidity > HUMIDITY_THRESHOLD_H)
        {
            *(int*)cntl_msg.param = 0;
            LOS_QueueWriteCopy(cntlCenter_qId, (void *)&cntl_msg, sizeof(cntl_msg), 1);
        }

        LOS_Msleep(1000);
    }

}
